package messages

import (
	"encoding/binary"
	"fmt"
	"io"
)

// RTPS完整消息
type Message struct {
	Header      Header
	Submessages []Submessage
}

// 创建新的RTPS消息
func NewMessage(guidPrefix [12]byte) *Message {
	return &Message{
		Header: Header{
			ProtocolID:      [4]byte{'R', 'T', 'P', 'S'},
			ProtocolVersion: Version{Major: 2, Minor: 2},
			VendorID:        0x0000,
			GUIDPrefix:      guidPrefix,
		},
		Submessages: make([]Submessage, 0),
	}
}

// 添加子消息
func (m *Message) AddSubmessage(submsg Submessage) {
	m.Submessages = append(m.Submessages, submsg)
}

// 序列化消息
func (m *Message) Write(w io.Writer) error {
	// 写入消息头
	if err := m.Header.Write(w); err != nil {
		return err
	}

	// 写入所有子消息
	for _, submsg := range m.Submessages {
		header := submsg.GetHeader()

		// 写入子消息头
		if err := binary.Write(w, binary.BigEndian, header.SubmessageID); err != nil {
			return err
		}
		if err := binary.Write(w, binary.BigEndian, header.Flags); err != nil {
			return err
		}
		if err := binary.Write(w, binary.BigEndian, header.SubmessageLength); err != nil {
			return err
		}

		// 写入子消息内容
		if err := submsg.Write(w); err != nil {
			return err
		}
	}

	return nil
}

// 反序列化消息
func (m *Message) Read(r io.Reader) error {
	// 读取消息头
	if err := m.Header.Read(r); err != nil {
		return err
	}

	// 验证消息头
	if err := m.Header.Validate(); err != nil {
		return err
	}

	// 读取所有子消息
	for {
		var submsgHeader SubmessageHeader

		// 读取子消息头
		if err := binary.Read(r, binary.BigEndian, &submsgHeader.SubmessageID); err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		if err := binary.Read(r, binary.BigEndian, &submsgHeader.Flags); err != nil {
			return err
		}
		if err := binary.Read(r, binary.BigEndian, &submsgHeader.SubmessageLength); err != nil {
			return err
		}

		// 根据子消息ID创建相应的子消息
		submsg, err := createSubmessage(submsgHeader.SubmessageID)
		if err != nil {
			return err
		}

		submsg.GetHeader().SubmessageID = submsgHeader.SubmessageID
		submsg.GetHeader().Flags = submsgHeader.Flags
		submsg.GetHeader().SubmessageLength = submsgHeader.SubmessageLength

		// 读取子消息内容
		if err := submsg.Read(r); err != nil {
			return err
		}

		m.Submessages = append(m.Submessages, submsg)
	}

	return nil
}

// 根据子消息ID创建子消息实例
func createSubmessage(submessageID uint8) (Submessage, error) {
	switch submessageID {
	case 0x01: // InfoTimestamp
		return &InfoTimestamp{}, nil
	case 0x06: // InfoDestination
		return &InfoDestination{}, nil
	case 0x15: // Data
		return &Data{}, nil
	case 0x07: // Heartbeat
		return &Heartbeat{}, nil
	default:
		return nil, fmt.Errorf("unsupported submessage type: 0x%02x", submessageID)
	}
}

// 获取消息大小估算
func (m *Message) EstimatedSize() int {
	size := 20 // 消息头固定大小

	for _, submsg := range m.Submessages {
		header := submsg.GetHeader()
		size += 4 // 子消息头大小
		size += int(header.SubmessageLength)
	}

	return size
}
